#include "rulechecker.h"
#include "game.h"
#include <algorithm>

// 构造函数实现
RuleChecker::RuleChecker(const Board* b, Game* g) 
    : board(b), game(g) 
{}

// 公有函数 isValidMove 实现
bool RuleChecker::isValidMove(Pos from, Pos to)
{
    // 起点和终点不能相同
    if (from == to)
    {
        return false;
    }
    // 起点必须要有棋子
    ChessDef::pieceID piece = board->getPieceAt(from);
    if (piece == ChessDef::kong)
    {
        return false;
    }
    // 终点不能是己方棋子
    ChessDef::pieceID target = board->getPieceAt(to);
    if (target != ChessDef::kong && ChessDef::isRed(piece) == ChessDef::isRed(target))
    {
        return false;
    }
    // 根据棋子的类型进行对应规则的校验
    switch (piece)
    {
        case ChessDef::rche:
        case ChessDef::bche:
            return checkche(from, to);
        case ChessDef::rma:
        case ChessDef::bma:
            return checkma(from, to);
        case ChessDef::rxiang:
        case ChessDef::bxiang:
            return checkxiang(from, to);
        case ChessDef::rshi:
        case ChessDef::bshi:
            return checkshi(from, to);
        case ChessDef::shuai:
        case ChessDef::jiang:
            return checkShuaiJiang(from, to);
        case ChessDef::rpao:
        case ChessDef::bpao:
            return checkpao(from, to);
        case ChessDef::bing:
        case ChessDef::zu:
            return checkBingZu(from, to);
        default:
            return false; // 防止遗漏case
    }
}

// 私有函数 checkche 实现
bool RuleChecker::checkche(Pos from, Pos to)
{
    // 判断走的是不是直线
    if (from.row != to.row && from.col != to.col)
    {
        return false;
    }
    // 判断移动的方向方便遍历
    if (from.row == to.row && from.col != to.col) // x轴方向移动
    {
        int minCol = std::min(from.col, to.col);
        int maxCol = std::max(from.col, to.col);
        // 遍历那段距离判断中间有没有障碍物
        for (int col = minCol + 1; col < maxCol; col++)
        {
            if (board->getPieceAt(Pos(from.row, col)) != ChessDef::kong)
            {
                return false;
            }
        }
    }
    else // y轴方向移动
    {
        int minRow = std::min(from.row, to.row);
        int maxRow = std::max(from.row, to.row);
        for (int row = minRow + 1; row < maxRow; row++)
        {
            if (board->getPieceAt(Pos(row, from.col)) != ChessDef::kong)
            {
                return false;
            }
        }
    }
    return true;
}

// 私有函数 checkma 实现
bool RuleChecker::checkma(Pos from, Pos to)
{
    // 马走日且不绊马腿
    // 马走日，要么两行一列，要么两列一行
    int rownum = std::abs(from.row - to.row);
    int colnum = std::abs(from.col - to.col);
    if (!((rownum == 2 && colnum == 1) || (rownum == 1 && colnum == 2)))
    {
        return false;
    }
    // 不绊马腿，走两行时第一行不能有棋子绊腿
    if (rownum == 2)
    {
        int legrow = from.row + ((to.row > from.row) ? (1) : (-1));
        if (board->getPieceAt(Pos(legrow, from.col)) != ChessDef::kong)
        {
            return false;
        }
    }
    else
    {
        int legcol = from.col + ((to.col > from.col) ? (1) : (-1));
        if (board->getPieceAt(Pos(from.row, legcol)) != ChessDef::kong)
        {
            return false;
        }
    }
    return true;
}

// 私有函数 checkxiang 实现
bool RuleChecker::checkxiang(Pos from, Pos to)
{
    // 象走田不能过河中间不能有棋子
    // 象走田，两行两列
    int rownum = std::abs(from.row - to.row);
    int colnum = std::abs(from.col - to.col);
    if ((rownum != 2) || (colnum != 2))
    {
        return false;
    }
    // 黑象红相不能过河
    bool isRed = ChessDef::isRed(board->getPieceAt(from));
    if (isRed && to.col > 4)
    {
        return false;
    }
    if (!isRed && to.col < 5)
    {
        return false;
    }
    // 中间不能有阻挡
    int midrow = (from.row + to.row) / 2;
    int midcol = (from.col + to.col) / 2;
    if (board->getPieceAt(Pos(midrow, midcol)) != ChessDef::kong)
    {
        return false;
    }
    return true;
}

// 私有函数 checkshi 实现
bool RuleChecker::checkshi(Pos from, Pos to)
{
    // 士走对角，九宫格内
    // 九宫格内
    bool isRed = ChessDef::isRed(board->getPieceAt(from));
    if (isRed)
    {
        if (to.row < 3 || to.row > 5 || to.col < 0 || to.col > 2)
        {
            return false;
        }
    }
    else
    {
        if (to.row < 3 || to.row > 5 || to.col > 9 || to.col < 7)
        {
            return false;
        }
    }
    // 走对角
    int rownum = std::abs(from.row - to.row);
    int colnum = std::abs(from.col - to.col);
    if (rownum != 1 || colnum != 1)
    {
        return false;
    }
    return true;
}

// 私有函数 checkShuaiJiang 实现
bool RuleChecker::checkShuaiJiang(Pos from, Pos to)
{
    // 九宫格内，走一步直线，帅将不照面
    // 九宫格内
    bool isRed = ChessDef::isRed(board->getPieceAt(from));
    if (isRed)
    {
        if (to.row < 3 || to.row > 5 || to.col < 0 || to.col > 2)
        {
            return false;
        }
    }
    else
    {
        if (to.row < 3 || to.row > 5 || to.col > 9 || to.col < 7)
        {
            return false;
        }
    }
    // 走一步直线
    int rownum = std::abs(from.row - to.row);
    int colnum = std::abs(from.col - to.col);
    if (!((rownum == 1 && colnum == 0) || (rownum == 0 && colnum == 1)))
    {
        return false;
    }
    // 将帅不照面
    if (isRed)
    {
        Pos jiangPos = findJiangPos();
        if (to.row == jiangPos.row)
        {
            int start = std::min(to.col, jiangPos.col) + 1;
            int end = std::max(to.col, jiangPos.col);
            if (isRowClear(start, end, to.row))
            {
                game->setGameOver(false);
                return true;
            }
        }
    }
    else
    {
        Pos shuaiPos = findShuaiPos();
        if (to.row == shuaiPos.row)
        {
            int start = std::min(to.col, shuaiPos.col) + 1;
            int end = std::max(to.col, shuaiPos.col);
            if (isRowClear(start, end, to.row))
            {
                game->setGameOver(true);
                return true;
            }
        }
    }
    return true;
}

// 私有函数 findJiangPos 实现
Pos RuleChecker::findJiangPos()
{
    for (int col = 7; col <= 9; col++)
    {
        for (int row = 3; row <= 5; row++)
        {
            if (board->getPieceAt(Pos(row, col)) == ChessDef::jiang)
            {
                return Pos(row, col);
            }
        }
    }
    return Pos(-1, -1);
}

// 私有函数 findShuaiPos 实现
Pos RuleChecker::findShuaiPos()
{
    for (int col = 0; col <= 2; col++)
    {
        for (int row = 3; row <= 5; row++)
        {
            if (board->getPieceAt(Pos(row, col)) == ChessDef::shuai)
            {
                return Pos(row, col);
            }
        }
    }
    return Pos(-1, -1);
}

// 私有函数 isRowClear 实现（修复漏返回值问题）
bool RuleChecker::isRowClear(int start, int end, int row)
{
    for (int col = start; col < end; col++)
    {
        if (board->getPieceAt(Pos(row, col)) != ChessDef::kong)
        {
            return false; // 有阻挡
        }
    }
    return true; //无阻挡时返回true
}

// 私有函数 checkpao 实现
bool RuleChecker::checkpao(Pos from, Pos to)
{
    // 炮走直线，隔山打牛
    // 走直线
    if (from.row != to.row && from.col != to.col)
    {
        return false;
    }
    // 隔山打牛
    int count = 0;
    if (from.row == to.row)
    {
        int minCol = std::min(from.col, to.col);
        int maxCol = std::max(from.col, to.col);
        for (int Col = minCol + 1; Col < maxCol; Col++)
        {
            if (board->getPieceAt(Pos(from.row, Col)) != ChessDef::kong)
            {
                count++;
            }
        }
    }
    else
    {
        int minRow = std::min(from.row, to.row);
        int maxRow = std::max(from.row, to.row);
        for (int Row = minRow + 1; Row < maxRow; Row++)
        {
            if (board->getPieceAt(Pos(Row, from.col)) != ChessDef::kong)
            {
                count++;
            }
        }
    }
    ChessDef::pieceID target = board->getPieceAt(to);
    if (target == ChessDef::kong)
    {
        if (count != 0)
        {
            return false;
        }
    }
    else
    {
        if (count != 1)
        {
            return false;
        }
    }
    return true;
}

// 私有函数 checkBingZu 实现
bool RuleChecker::checkBingZu(Pos from, Pos to)
{
    // 兵没过河之前只能走直线，过了河之后可以走左右，不能后退，一次只能走一步
    bool isRed = ChessDef::isRed(board->getPieceAt(from));
    int rownum = std::abs(from.row - to.row);
    int colnum = to.col - from.col; 
    // 一次只能走一步
    if (std::abs(colnum) + rownum != 1)
    {
        return false;
    }
    // 不能后退，走直线没过河之前
    if (isRed)
    {
        if (colnum < 0) // 红兵不能后退（假设col增大为前进方向）
        {
            return false;
        }
        if (from.col < 5 && rownum != 0) // 没过河（col<5）不能左右走（rownum≠0）
        {
            return false;
        }
    }
    else
    {
        if (colnum > 0) // 黑卒不能后退（col减小为前进方向）
        {
            return false;
        }
        if (from.col > 4 && rownum != 0) // 没过河（col>4）不能左右走
        {
            return false;
        }
    }
    return true;
}